import { CombinationType } from "./Enum";

/**
 * 方块的坐标
 */
export default class Coordinate {
    /** 横坐标 */
    public x: number;
    /** 纵坐标 */
    public y: number;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    /**
     * 设置坐标
     * @param x 横坐标
     * @param y 纵坐标
     */
    public set(x: number | Coordinate, y?: number) {
        if (typeof x === 'number') {
            this.x = x;
            this.y = y;
        } else {
            this.x = x.x;
            this.y = x.y;
        }
    }

    /**
     * 复制对象
     * @returns 
     */
    public copy(): Coordinate {
        return new Coordinate(this.x, this.y);
    }

    /**
     * 比较
     * @param x 
     * @param y 
     */
    public compare(x: number | Coordinate, y?: number): boolean {
        let result = false;
        if (typeof x === 'number') {
            result = this.x === x && this.y === y;
        } else {
            result = this.x === x.x && this.y === x.y;
        }
        return result;
    }

    /**
     * 是否相邻
     * @param coord 
     */
    public isAdjacent(coord: Coordinate): boolean {
        let adjacent = false;
        if ( this.x === coord.x && (this.y === (coord.y - 1) || this.y === (coord.y + 1)) ) {
            // 上下相邻
            adjacent =  true;
        } else if ( this.y === coord.y && (this.x === (coord.x - 1) || this.x === (coord.x + 1)) ) {
            // 左右相邻
            adjacent =  true;
        } else {
            adjacent =  false;
        }
        return adjacent;
    }

    /**
     * 
     * @returns 
     */
    public toString(): string {
        return '(x:' + this.x + ', y:' + this.y + ')';
    }
}

export function Coord(x: number = 0, y: number = 0): Coordinate {
    return new Coordinate(x, y);
}

/**
 * 组合
 */
export class Combination {
    /** 坐标集 */
    public coords: Coordinate[];
    /** 共同坐标 */
    public commonCoord: Coordinate;
    /** 组合类型 */
    public type: CombinationType

    /**
     * 
     * @param coords 一组方块坐标
     */
    constructor(coords: Coordinate[]) {
        this.coords = coords;
        this.updateType();
    }

    /**
     * 更新组合类型
     */
    private updateType() {
        let up = 0;
        let down = 0;
        let left = 0;
        let right = 0;
        // 关键坐标，如果没有公共方块，则从组合方块中的第一个方块指定为公共方块
        let keyCoord = this.commonCoord ? this.commonCoord : this.coords[0];
        // 收集数量
        for (let i = 0; i < this.coords.length; i++) {
            // 同一个坐标时跳过
            if (this.coords[i].compare(keyCoord)) {
                continue;
            }
            // 判断位置
            if (this.coords[i].x === keyCoord.x) {      // 组合方块和公共方块在同Y轴
                if (this.coords[i].y > keyCoord.y) {
                    up++;
                } else {
                    down++;
                }
            } else {                                    // 组合方块和公共方块在同X轴
                if (this.coords[i].x > keyCoord.x) {
                    right++
                } else {
                    left++;
                }
            }
        }
        // 判断组合类型
        if (up === 0 && down === 0) {
            this.type = CombinationType.Horizontal;
        } else if (left === 0 && right === 0) {
            this.type = CombinationType.Vertical;
        } else if (up > 0 && down > 0 && right > 0 && left > 0) {
            this.type = CombinationType.Cross;
        } else if ((up > 0 && down === 0 && left === 0 && right > 0) ||
            (up > 0 && down === 0 && left > 0 && right === 0) ||
            (up === 0 && down > 0 && left > 0 && right === 0) ||
            (up === 0 && down > 0 && left === 0 && right > 0)) {
            this.type = CombinationType.LShape;
        } else if ((up === 0 && down > 0 && left > 0 && right > 0) ||
            (up > 0 && down === 0 && left > 0 && right > 0) ||
            (up > 0 && down > 0 && left === 0 && right > 0) ||
            (up > 0 && down > 0 && left > 0 && right === 0)) {
            this.type = CombinationType.TShape;
        }
    }

    /**
     * 返回组合坐标集和指定坐标集交叉的共同坐标
     * @param coords 指定坐标集
     * @returns 
     */
    public include(coords: Coordinate[]): Coordinate {
        for (let i = 0; i < this.coords.length; i++) {
            for (let j = 0; j < coords.length; j++) {
                if (this.coords[i].compare(coords[j])) {
                    return coords[j];
                }
            }
        }
        return null;
    }

    /**
     * 合并有交集的两个坐标集
     * @param coords 
     * @param commonCoord 
     */
    public merge(coords: Coordinate[], commonCoord: Coordinate) {
        for (let i = 0; i < coords.length; i++) {
            if (!coords[i].compare(commonCoord)) {
                this.coords.push(coords[i]);
            }
        }
        this.commonCoord = commonCoord;
        this.updateType();
    }
}